﻿/*   
    Copyright (C) 2009 Galaktika Corporation ZAO

    This file is a part of Galaktika.BusinessMonitor
 
    Galaktika.BusinessMonitor is a free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
      
    You should have received a copy of the GNU General Public License
    along with Galaktika.BusinessMonitor.  If not, see <http://www.gnu.org/licenses/>.
  
    If GPL v.3 is not suitable for your products or company,
    Galaktika Corp provides Galaktika.BusinessMonitor under a flexible commercial license
    designed to meet your specific usage and distribution requirements.
    If you have already obtained a commercial license from Galaktika Corp,
    you can use this file under those license terms.
*/

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Ranet.AgOlap.Controls.General;
using Galaktika.BI.Runtime.Services;
using Ranet.Olap.Core.Providers.ClientServer;
using Galaktika.BI.Silverlight.Services;
using Galaktika.BI.Silverlight.Commands;
using Ranet.Olap.Core;
using Galaktika.BI.Silverlight.Controls.PivotMdxDesigner;
using Galaktika.BI.Extensibility.Dom.Dac;
using Ranet.AgOlap.Controls.General.ClientServer;
using Ranet.Olap.Core.Metadata;
using Ranet.AgOlap.Controls.MemberChoice.ClientServer;
using Ranet.ZipLib;

namespace Galaktika.BI.Silverlight.Controls.General
{
    public class OlapDataLoaderEx : IDataLoader
    {
        public IBindingContext Context { get; set; }
        public IBindingManager BindManager { get; set; }
        UserControl Owner = null;

        public OlapDataLoaderEx(UserControl owner)
            : base()
        {
            Owner = owner;
        }

        String DataSourceId
        {
            get
            {
                if (BindManager != null)
                {
                    return BindManager.DataManager.Name;
                }
                return String.Empty;
            }
        }

        #region IDataLoader Members

        public void LoadData(OlapActionBase schema, object state)
        {
            if (schema != null)
            {
                IUserTaskManager taskManager = (IUserTaskManager)Context.Services.GetService(typeof(IUserTaskManager));
                if (taskManager != null)
                {
                    InvokeSchema invokeSchema = null;
                    String taskText = String.Empty;

                    PivotInitializeArgs initialize_args = schema as PivotInitializeArgs;
                    if (initialize_args != null)
                    {
                        invokeSchema = CommandBuilder.CreateGetPivotDataSchema((string)this.Context.UserData["_$Id"], DataSourceId, initialize_args);
                        taskText = Localization.AppTask_DownloadingPivotData;
                    }

                    MdxQueryArgs mdx_args = schema as MdxQueryArgs;
                    if (mdx_args != null)
                    {
                        invokeSchema = CommandBuilder.CreateExecuteQuerySchema((string)this.Context.UserData["_$Id"], DataSourceId, mdx_args.Connection, mdx_args);
                        taskText = Localization.AppTask_ExecutingMDX;
                    }

                    PerformMemberActionArgs memberAction_args = schema as PerformMemberActionArgs;
                    if (memberAction_args != null)
                    {
                        invokeSchema = CommandBuilder.CreateDrillDownSchema((string)this.Context.UserData["_$Id"], DataSourceId, memberAction_args);
                        taskText = Localization.AppTask_ExecutingDrillAction;
                        switch (memberAction_args.Action)
                        {
                            case MemberActionType.Collapse:
                                taskText = Localization.AppTask_ExecutingCollapseAction;
                                break;
                            case MemberActionType.DrillDown:
                                taskText = Localization.AppTask_ExecutingDrillDownAction;
                                break;
                            case MemberActionType.Expand:
                                taskText = Localization.AppTask_ExecutingExpandAction;
                                break;
                        }
                    }

                    ServiceCommandArgs service_args = schema as ServiceCommandArgs;
                    if (service_args != null)
                    {
                        invokeSchema = CommandBuilder.CreateRunServiceCommandSchema((string)this.Context.UserData["_$Id"], DataSourceId, service_args);
                        taskText = String.Empty;

                        ServiceCommandType actionType = service_args.Command;
                        switch (actionType)
                        {
                            case ServiceCommandType.Back:
                            case ServiceCommandType.Forward:
                                taskText = String.Format(Localization.AppTask_ExecutingNavigationCommand, actionType.ToString());
                                break;
                            default:
                                taskText = String.Format(Localization.AppTask_ExecutingServiceCommand, actionType.ToString());
                                break;
                        }
                    }

                    PivotGridToolBarInfo toolBar_args = schema as PivotGridToolBarInfo;
                    if (toolBar_args != null)
                    {
                        invokeSchema = CommandBuilder.CreateToolBarInfoSchema((string)this.Context.UserData["_$Id"], DataSourceId);
                    }

                    UpdateCubeArgs update_args = schema as UpdateCubeArgs;
                    if (update_args != null)
                    {
                        var exe = (IExecutionContext)this.Context.Services.GetService(typeof(IExecutionContext));
                        if (exe != null)
                        {
                            var conn = exe.GetNamedObject(this.Context, this.DataSourceId) as BrickDataSource;
                            if (conn != null)
                            {
                                update_args.ConnectionString = exe.Parse(this.Context, conn.Connection.ConnectionString);
                            }
                        }

                        invokeSchema = CommandBuilder.CreateUpdateCubeSchema(
                            (string)this.Context.UserData["_$Id"],
                            DataSourceId,
                            update_args,
                            this.GetSessionId(update_args.ConnectionString));
                        taskText = Localization.AppTask_ExecutingUpdateCubeCommand;
                    }

                    ChangeDataSourceArgs change_args = schema as ChangeDataSourceArgs;
                    if(change_args != null)
                    {
                        invokeSchema = CommandBuilder.CreateChangeDataSourceSchema((string)this.Context.UserData["_$Id"], DataSourceId, change_args.Args);
                        taskText = Localization.AppTask_DownloadingPivotData;
                    }

                    MetadataQuery metadata_args = schema as MetadataQuery;
                    if (metadata_args != null)
                    {
                        invokeSchema = CommandBuilder.CreateGetMetadataSchema((string)this.Context.UserData["_$Id"], metadata_args.Connection, metadata_args);

                        switch (metadata_args.QueryType)
                        {
                            case MetadataQueryType.GetKPIs:
                                taskText = Localization.AppTask_DownloadingKPIs;
                                break;
                            case MetadataQueryType.GetKPI:
                                taskText = Localization.AppTask_DownloadingKPI;
                                break;
                            case MetadataQueryType.GetMeasures:
                                taskText = Localization.AppTask_DownloadingMeasures;
                                break;
                            case MetadataQueryType.GetMeasure:
                                taskText = String.Format(Localization.AppTask_DownloadingMeasure, metadata_args.MeasureUniqueName);
                                break;
                            case MetadataQueryType.GetDimension:
                                taskText = Localization.AppTask_DownloadingDimension;
                                break;
                            case MetadataQueryType.GetDimensions:
                                taskText = Localization.AppTask_DownloadingDimensions;
                                break;
                            case MetadataQueryType.GetHierarchy:
                                taskText = Localization.AppTask_DownloadingHierarchy;
                                break;
                            case MetadataQueryType.GetHierarchies:
                                taskText = Localization.AppTask_DownloadingHierarchies;
                                break;
                            case MetadataQueryType.GetLevels:
                                taskText = Localization.AppTask_DownloadingLevels;
                                break;
                            case MetadataQueryType.GetLevel:
                                taskText = String.Format(Localization.AppTask_DownloadingLevel, metadata_args.LevelUniqueName);
                                break;
                            case MetadataQueryType.GetLevelProperties:
                                taskText = Localization.AppTask_DownloadingLevelProperties;
                                break;
                            case MetadataQueryType.GetCubeMetadata:
                                taskText = Localization.AppTask_DownloadingCubeMetadata;
                                break;
                            default:
                                break;
                        }
                    }

                    MemberChoiceQuery members_args = schema as MemberChoiceQuery;
                    if (members_args != null)
                    {
                        invokeSchema = CommandBuilder.CreateMemberChoiceQuerySchema((string)this.Context.UserData["_$Id"], members_args.Connection, members_args);
                        switch (members_args.QueryType)
                        {
                            case MemberChoiceQueryType.FindMembers:
                                taskText = Localization.AppTask_FindingMembers;
                                break;
                            case MemberChoiceQueryType.GetAscendants:
                                taskText = String.Format(Localization.AppTask_DownloadingAscendants, members_args.MemberUniqueName);
                                break;
                            case MemberChoiceQueryType.GetChildrenMembers:
                                taskText = String.Format(Localization.AppTask_DownloadingChildrenMembersFor, members_args.MemberUniqueName);
                                break;
                            case MemberChoiceQueryType.GetRootMembers:
                                taskText = Localization.AppTask_DownloadingDimension;
                                break;
                            case MemberChoiceQueryType.GetRootMembersCount:
                                taskText = Localization.AppTask_CalcRootMembersCount;
                                break;
                            case MemberChoiceQueryType.GetMember:
                                taskText = String.Format(Localization.AppTask_DownloadingMemberProperties, members_args.MemberUniqueName);
                                break;
                            case MemberChoiceQueryType.GetMembers:
                                taskText = Localization.AppTask_DownloadingMembers;
                                break;
                            case MemberChoiceQueryType.LoadSetWithAscendants:
                                taskText = Localization.AppTask_DownloadingSelectedMembers;
                                break;
                            default:
                                break;
                        }
                    }

                    if (invokeSchema != null)
                    {
                        ChoiceControlInvokeSchemaWrapper wrapper = new ChoiceControlInvokeSchemaWrapper(invokeSchema, state);
                        taskManager.RunTaskAsync(
                            taskText,
                            param => this.InvokeCommand(param),
                            wrapper);
                    }
                }
                return;
            }
        }

        private string GetSessionId(string connectionString)
        {
            var sessionProvider = (IAdomdSessionProvider)this.Context.Services.GetService(typeof(IAdomdSessionProvider));
            if (sessionProvider != null)
            {
                return sessionProvider.GetSessionId(connectionString);
            }

            return null;
        }

        void InvokeCommand(object state)
        {
            ChoiceControlInvokeSchemaWrapper wrapper = state as ChoiceControlInvokeSchemaWrapper;
            if (wrapper != null)
            {
                InvokeSchema schema = wrapper.Schema;
                using (var cmd = CommandDispatcher.Dispatch(schema))
                {
                    InvokeResultSchema res = cmd.Invoke();

                    String content = res.Content;
                    if (res.IsArchive)
                    {
                        content = ZipCompressor.DecompressFromBase64String(res.Content);
                    }

                    InvokeResultDescriptor result = new InvokeResultDescriptor(content);
                    if (res.ContentType == KnownContentTypes.ADOMDError || 
                        res.ContentType == KnownContentTypes.Error)
                        result.ContentType = InvokeContentType.Error;

                    // MessageBox в случае возникновения ошибки в update скрипте сводной таблицы
                    if (schema.CommandId == Commands.CommandId.UpdateCubeCommandId ||
                        schema.CommandId == Commands.CommandId.CommitTransactionCommandId ||
                        schema.CommandId == Commands.CommandId.RollbackTransactionCommandId)
                    {
                        if (res.ContentType == KnownContentTypes.ADOMDError)
                        {
                            var output = (IOutputService)this.Context.Services.GetService(typeof(IOutputService));
                            if (output != null && Owner != null)
                            {
                                Owner.Dispatcher.BeginInvoke(() => output.ShowWarning(result.Content));
                            }
                        }
                    }

                    Raise_DataLoaded(new DataLoaderEventArgs(result, null, wrapper.UserState));
                }
            }
        }

        void Raise_DataLoaded(DataLoaderEventArgs args)
        {
            EventHandler<DataLoaderEventArgs> handler = this.DataLoaded;

            if (handler != null)
            {
                if (Owner != null)
                {
                    Owner.Dispatcher.BeginInvoke(delegate { handler(this, args); });
                }
                else
                {
                    handler(this, args);
                }
            }
        }

        #endregion

        #region IDataLoader Members

        public event EventHandler<DataLoaderEventArgs> DataLoaded;

        #endregion

    }
}
